package com.itcs.box.server.server;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import com.itcs.box.BoxConstants;
import com.itcs.box.server.service.NettyMsgResolveService;
import com.itcs.box.util.BoxResUtils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * 消息通道Handler
 * 
 * @author LiuPeng
 * 
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<ByteBuf> {

	private Log logger = LogFactory.getLog(getClass());

	private NettyMsgResolveService nettyMsgResolveService;

	public NettyServerHandler(NettyMsgResolveService nettyMsgResolveService) {
		this.nettyMsgResolveService = nettyMsgResolveService;
	}

	/*
	 * (非 Javadoc) <p>Title: userEventTriggered</p> <p>Description: </p>
	 * 
	 * @param ctx
	 * 
	 * @param evt
	 * 
	 * @throws Exception
	 * 
	 * @see
	 * io.netty.channel.ChannelInboundHandlerAdapter#userEventTriggered(io.netty.
	 * channel.ChannelHandlerContext, java.lang.Object)
	 */
	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
		if (evt instanceof IdleStateEvent) {
			IdleStateEvent e = (IdleStateEvent) evt;
			switch (e.state()) {
			case READER_IDLE:
				String deviceId = NettyChannelMap.getKeyByValue(ctx);
				if (deviceId == null) {
					deviceId = ctx.channel().remoteAddress().toString();
					logger.warn("客户端:" + deviceId + " 长时间无消息且未登录,强制断开连接");
					try {
						ctx.disconnect();
						ctx.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				} else {
					ByteBuf byteBuf = Unpooled.wrappedBuffer(JSON.toJSONString(BoxResUtils.build1002(deviceId)).getBytes(BoxConstants.CHARSET_UTF8));
					ctx.writeAndFlush(byteBuf);
					logger.info("客户端[" + deviceId + "] 长时间无消息,发送心跳测试");
				}
				break;
			case WRITER_IDLE:
				break;
			case ALL_IDLE:
				break;
			default:
				break;
			}
		}
	}
	
	/* (非 Javadoc)  
	 * <p>Title: exceptionCaught</p>  
	 * <p>Description: </p>  
	 * @param ctx
	 * @param cause
	 * @throws Exception  
	 * @see io.netty.channel.ChannelInboundHandlerAdapter#exceptionCaught(io.netty.channel.ChannelHandlerContext, java.lang.Throwable)  
	 */  
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		Channel incoming = ctx.channel();
        if(!incoming.isActive()) {
        	logger.info("客户端:" + ctx.channel().remoteAddress() + " 强制关闭连接");
        }
        ctx.close();
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
//		logger.info("客户端:" + ctx.channel().remoteAddress() + " 创建连接");
		super.channelActive(ctx);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		String deviceId = NettyChannelMap.getKeyByValue(ctx);
		if(deviceId!=null) {
			String channelId = NettyChannelMap.getChannelId(deviceId);
			NettyChannelMap.remove(deviceId);
			if(channelId!=null) {
				nettyMsgResolveService.channelInactive(ctx,deviceId,channelId);
			}
		}
	}

	@Override
	protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
		nettyMsgResolveService.resolve(channelHandlerContext, byteBuf);
		// ReferenceCountUtil.release(byteBuf);
	}
}
